package cn.com.ayqu.module.erp.controller.admin.sale;

import cn.com.ayqu.framework.apilog.core.annotation.ApiAccessLog;
import cn.com.ayqu.framework.common.enums.CommonStatusEnum;
import cn.com.ayqu.framework.common.pojo.CommonResult;
import cn.com.ayqu.framework.common.pojo.PageParam;
import cn.com.ayqu.framework.common.pojo.PageResult;
import cn.com.ayqu.framework.common.util.collection.MapUtils;
import cn.com.ayqu.framework.common.util.object.BeanUtils;
import cn.com.ayqu.framework.excel.core.util.ExcelUtils;
import cn.com.ayqu.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.com.ayqu.module.erp.controller.admin.sale.vo.customer.*;
import cn.com.ayqu.module.erp.dal.dataobject.sale.ErpCustomerCarNumberDO;
import cn.com.ayqu.module.erp.dal.dataobject.sale.ErpCustomerDO;
import cn.com.ayqu.module.erp.dal.mysql.sale.ErpCustomerCarNumberMapper;
import cn.com.ayqu.module.erp.service.sale.ErpCustomerService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static cn.com.ayqu.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.com.ayqu.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.com.ayqu.framework.common.pojo.CommonResult.error;
import static cn.com.ayqu.framework.common.pojo.CommonResult.success;
import static cn.com.ayqu.framework.common.util.collection.CollectionUtils.convertList;
import static cn.com.ayqu.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.com.ayqu.module.erp.enums.ErrorCodeConstants.NO_DATA_EXPORT;

@Tag(name = "管理后台 - ERP 客户")
@RestController
@RequestMapping("/erp/customer")
@Validated
public class ErpCustomerController {

    @Resource
    private ErpCustomerService customerService;

    @Resource
    private ErpCustomerCarNumberMapper customerCarNumberMapper;

    @PostMapping("/create")
    @Operation(summary = "创建客户")
    @PreAuthorize("@ss.hasPermission('erp:customer:create')")
    public CommonResult<Long> createCustomer(@Valid @RequestBody ErpCustomerSaveReqVO createReqVO) {
        return success(customerService.createCustomer(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新客户")
    @PreAuthorize("@ss.hasPermission('erp:customer:update')")
    public CommonResult<Boolean> updateCustomer(@Valid @RequestBody ErpCustomerSaveReqVO updateReqVO) {
        customerService.updateCustomer(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除客户")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('erp:customer:delete')")
    public CommonResult<Boolean> deleteCustomer(@RequestParam("id") Long id) {
        customerService.deleteCustomer(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得客户")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('erp:customer:query')")
    public CommonResult<ErpCustomerRespVO> getCustomer(@RequestParam("id") Long id) {
        List<ErpCustomerCarNumberDO> customerCarNumberList = customerService.getCustomerCarNumberList(id);

        return success(BeanUtils.toBean(customerService.getCustomer(id), ErpCustomerRespVO.class, customer -> {
            List<ErpCustomerRespVO.Item> carNumberList = new ArrayList<>();
            for (ErpCustomerCarNumberDO carNumberDO : customerCarNumberList) {
                carNumberList.add(new ErpCustomerRespVO.Item()
                        .setCarNumberId(carNumberDO.getId())
                        .setCarNumber(carNumberDO.getCarNumber())
                );
            }

            customer.setCarNumbers(customerCarNumberList.stream().map(ErpCustomerCarNumberDO::getCarNumber).toList())
                    .setCarNumberList(carNumberList);
        }));
    }

    @GetMapping("/page")
    @Operation(summary = "获得客户分页")
    @PreAuthorize("@ss.hasPermission('erp:customer:query')")
    public CommonResult<PageResult<ErpCustomerRespVO>> getCustomerPage(@Valid ErpCustomerPageReqVO pageReqVO) {
        if (StringUtils.isNotBlank(pageReqVO.getCarNumber())) {
            List<ErpCustomerCarNumberDO> carNumberDOList = customerCarNumberMapper.selectList(new LambdaQueryWrapperX<ErpCustomerCarNumberDO>()
                    .like(ErpCustomerCarNumberDO::getCarNumber, pageReqVO.getCarNumber())
                    .and(q ->
                            q.eq(ErpCustomerCarNumberDO::getDeleted, 1)
                                    .or()
                                    .eq(ErpCustomerCarNumberDO::getDeleted, 0)
                    )
            );

            if (carNumberDOList.isEmpty()) {
                return success(PageResult.empty());
            }

            pageReqVO.setUserIds(carNumberDOList.stream().map(ErpCustomerCarNumberDO::getCustomerId).toList());
        }

        PageResult<ErpCustomerDO> pageResult = customerService.getCustomerPage(pageReqVO);
        if (pageResult.getList().isEmpty()) {
            return success(PageResult.empty());
        }
        Map<Long, List<ErpCustomerCarNumberDO>> carNumberMap = customerService.getCustomerAllCarNumberMap(
                convertSet(pageResult.getList(), ErpCustomerDO::getId));

        return success(BeanUtils.toBean(pageResult, ErpCustomerRespVO.class, customer -> {
            MapUtils.findAndThen(carNumberMap, customer.getId(), carNumber -> {
                List<String> carNumberList = new ArrayList<>();
                for (ErpCustomerCarNumberDO carNumberDO : carNumber) {
                    if (!carNumberDO.getDeleted()) {
                        carNumberList.add(carNumberDO.getCarNumber());
                    }
                }
                customer.setCarNumbers(carNumberList);
            });
        }));
    }

    @GetMapping("/simple-list")
    @Operation(summary = "获得客户精简列表", description = "只包含被开启的客户，主要用于前端的下拉选项")
    public CommonResult<List<ErpCustomerRespVO>> getCustomerSimpleList() {
        List<ErpCustomerDO> list = customerService.getCustomerListByStatus(CommonStatusEnum.ENABLE.getStatus());
        return success(convertList(list, customer -> new ErpCustomerRespVO().setId(customer.getId()).setName(customer.getName())));
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出客户 Excel")
    @PreAuthorize("@ss.hasPermission('erp:customer:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportCustomerExcel(@Valid ErpCustomerPageReqVO pageReqVO,
              HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);

        if (StringUtils.isNotBlank(pageReqVO.getCarNumber())) {
            List<ErpCustomerCarNumberDO> carNumberDOList = customerCarNumberMapper.selectList(new LambdaQueryWrapperX<ErpCustomerCarNumberDO>()
                    .like(ErpCustomerCarNumberDO::getCarNumber, pageReqVO.getCarNumber())
                    .and(q ->
                            q.eq(ErpCustomerCarNumberDO::getDeleted, 1)
                                    .or()
                                    .eq(ErpCustomerCarNumberDO::getDeleted, 0)
                    )
            );

            if (carNumberDOList.isEmpty()) {
                throw exception(NO_DATA_EXPORT);
            }

            pageReqVO.setUserIds(carNumberDOList.stream().map(ErpCustomerCarNumberDO::getCustomerId).toList());
        }

        List<ErpCustomerDO> list = customerService.getCustomerPage(pageReqVO).getList();
        if (list.isEmpty()) {
            throw exception(NO_DATA_EXPORT);
        }
        Map<Long, List<ErpCustomerCarNumberDO>> carNumberMap = customerService.getCustomerAllCarNumberMap(
                convertSet(list, ErpCustomerDO::getId));

        // 导出 Excel
        ExcelUtils.write(response, "客户.xls", "数据", ErpCustomerRespVO.class,
                        BeanUtils.toBean(list, ErpCustomerRespVO.class, customer -> {
                            MapUtils.findAndThen(carNumberMap, customer.getId(), carNumber -> {
                                List<String> carNumberList = carNumber.stream().map(ErpCustomerCarNumberDO::getCarNumber).toList();
                                customer.setCarNumbersStr(String.join(",", carNumberList));
                            });
                        }));
    }

    @GetMapping("/getCustomerCarNumber")
    @Operation(summary = "获得客户车牌号")
    public CommonResult<List<ErpCustomerCarNumberDO>> getCustomerCarNumber(@RequestParam("customerId") Long customerId) {
        List<ErpCustomerCarNumberDO> carNumberList = customerService.getCustomerCarNumberList(customerId);
        return success(carNumberList);
    }

    @GetMapping("/getCustomerCarNumberPage")
    @Operation(summary = "获得客户车牌号分页")
    public CommonResult<PageResult<ErpCustomerCarNumberDO>> getCustomerCarNumberPage(@Valid ErpCustomerCarNumberPageReqVO pageReqVO) {
        PageResult<ErpCustomerCarNumberDO> pageResult = customerCarNumberMapper.selectPage(pageReqVO, new LambdaQueryWrapperX<ErpCustomerCarNumberDO>()
                .like(ErpCustomerCarNumberDO::getCarNumber, pageReqVO.getCarNumber())
                .and(q ->
                        q.eq(ErpCustomerCarNumberDO::getDeleted, 1)
                                .or()
                                .eq(ErpCustomerCarNumberDO::getDeleted, 0)
                )
        );

        return success(pageResult);
    }

    @GetMapping("/getCustomerMorePage")
    @Operation(summary = "获取客户更多信息分页")
    public CommonResult<PageResult<ErpCustomerMoreRespVO>> getCustomerMorePage(@Valid ErpCustomerMorePageReqVO pageReqVO) {
        return success(customerService.getCustomerMorePage(pageReqVO));
    }
}